package com.zsx.shopping.cart.service.impl;

import com.zsx.shopping.cart.constant.CartConstant;
import com.zsx.shopping.cart.converter.CartItemConverter;
import com.zsx.shopping.cart.interceptor.LoginInterceptor;
import com.zsx.shopping.cart.service.CartService;
import com.zsx.shopping.common.api.cart.vo.CartItemVO;
import com.zsx.shopping.common.api.cart.vo.CartVO;
import com.zsx.shopping.common.api.order.feign.OrderFeignService;
import com.zsx.shopping.common.api.product.feign.ProductFeignService;
import com.zsx.shopping.common.api.product.vo.SkuVO;
import com.zsx.shopping.common.exception.ShoppingException;
import com.zsx.shopping.common.session.UserVO;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class CartServiceImpl implements CartService {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    private ProductFeignService productFeignService;

    @Resource
    private OrderFeignService orderFeignService;

    @Resource
    private CartItemConverter cartItemConverter;

    @Override
    public void addToCart(Long skuId, Integer count) {
        BoundHashOperations<String, Long, CartItemVO> cartOps = getCartOps();
        CartItemVO cartItemVo = cartOps.get(skuId);
        if (cartItemVo != null) {
            cartItemVo.setCount(cartItemVo.getCount() + count);
        } else {
            SkuVO skuVO = productFeignService.getSkus(Collections.singletonList(skuId)).getData().get(0);
            cartItemVo = cartItemConverter.toCartItemVo(skuVO, count);
        }
        cartOps.put(skuId, cartItemVo);
    }

    @Override
    public void clearCart() {
        UserVO userVO = LoginInterceptor.loginUser.get();
        String cartKey = CartConstant.CART_PREFIX + userVO.getId();
        redisTemplate.delete(cartKey);
    }

    @Override
    public void updateCart() {
        BoundHashOperations<String, Long, CartItemVO> cartOps = getCartOps();
        List<CartItemVO> cartItemVOs = cartOps.values();
        if (!CollectionUtils.isEmpty(cartItemVOs)) {
            int size = cartItemVOs.size();
            List<Long> skuIds = new ArrayList<>(size);
            List<Integer> counts = new ArrayList<>(size);
            cartItemVOs.forEach(cartItemVO -> {
                skuIds.add(cartItemVO.getSkuId());
                counts.add(cartItemVO.getCount());
            });
            Map<Long, SkuVO> skuVOMap = productFeignService.getSkus(skuIds).getData()
                    .stream().collect(Collectors.toMap(SkuVO::getId, Function.identity()));
            HashMap<Long, CartItemVO> map = new HashMap<>(size);
            for (int i = 0; i < size; i++) {
                Long skuId = skuIds.get(i);
                map.put(skuId, cartItemConverter.toCartItemVo(skuVOMap.get(skuId), counts.get(i)));
            }
            cartOps.putAll(map);
        }
    }

    @Override
    public String toTrade() {
        Long size = getCartOps().size();
        if (size == null || size == 0) {
            throw new ShoppingException("请添加商品到购物车再结算");
        }
        return orderFeignService.toTrade().getData();
    }

    @Override
    public void changeCount(Long skuId, Integer count) {
        BoundHashOperations<String, Long, CartItemVO> cartOps = this.getCartOps();
        CartItemVO cartItemVo = cartOps.get(skuId);
        if (cartItemVo != null) {
            cartItemVo.setCount(count);
            cartOps.put(skuId, cartItemVo);
        }
    }

    @Override
    public CartVO getCart() {
        CartVO cartVO = new CartVO();
        List<CartItemVO> cartItemVos = getCartOps().values();
        cartVO.setItems(cartItemVos == null ? new ArrayList<>() : cartItemVos);
        return cartVO;
    }

    @Override
    public void delete(Long skuId) {
        getCartOps().delete(skuId);
    }

    private BoundHashOperations<String, Long, CartItemVO> getCartOps() {
        UserVO userVO = LoginInterceptor.loginUser.get();
        String cartKey = CartConstant.CART_PREFIX + userVO.getId();
        return redisTemplate.boundHashOps(cartKey);
    }
}
